﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Hosting;
using Xenta;
#if CLOUD
using Microsoft.WindowsAzure.ServiceRuntime;
#endif

namespace IisHost
{
    public sealed class Environment : IEnvironment
    {
        public string WorkingDir
        {
            get;
            set;
        }

        public string DataDir
        {
            get;
            set;
        }

        public string BinDir
        {
            get;
            set;
        }

        public WindowsIdentity WorkingIdentity
        {
            get;
            set;
        }
    }

    public static class HostRuntime
    {
        #region Fields

        private static readonly object _lock = new Object();
        private static readonly List<String> _state = new List<String>();
        private static readonly List<IInfrastructure> _infrastructures = new List<IInfrastructure>();
        private static volatile bool _initialized = false;

        #endregion

        #region Properties

        public static IEnumerable<String> State
        {
            get
            {
                return _state;
            }
        }

        public static Guid RuntimeGuid
        {
            get
            {
                string guidStr = ConfigurationManager.AppSettings["Runtime.Guid"];
                if(String.IsNullOrWhiteSpace(guidStr))
                    return Guid.Empty;
                return Guid.Parse(guidStr);
            }
        }

        public static bool Initialized
        {
            get
            {
                return _initialized;
            }
        }

        public static IEnumerable<IInfrastructure> Infrastructures
        {
            get
            {
                return _infrastructures;
            }
        }

        #endregion

        #region Methods

        public static void Initialize()
        {
            if(_initialized || RuntimeGuid.Equals(Guid.Empty))
                return;
            lock(_lock)
            {
                if(_initialized)
                    return;

                log4net.Config.XmlConfigurator.Configure();

                _state.Clear();

                _state.Add(String.Format("Initialize time: {0}", DateTime.UtcNow));
                _state.Add(String.Format("Runtime GUID: {0}", RuntimeGuid));
#if CLOUD
                _state.Add(String.Format("DeploymentId: {0}", RoleEnvironment.DeploymentId));
#endif

                var workingIdentity = WindowsIdentity.GetCurrent();
                var workingDir = new DirectoryInfo(HostingEnvironment.MapPath("~"));
                var appDataDir = new DirectoryInfo(HostingEnvironment.MapPath("~/App_Data"));
                var binDir = new DirectoryInfo(HostingEnvironment.MapPath("~/bin"));

                _state.Add(String.Format("Working identity: {0}", workingIdentity.Name));
                _state.Add(String.Format("Working directory: {0}", workingDir.FullName));
                _state.Add(String.Format("Data directory: {0}", appDataDir.FullName));
                _state.Add(String.Format("Binaries directory: {0}", binDir.FullName));

                foreach(var i in appDataDir.GetDirectories())
                {
                    _state.Add(String.Format("Build infrastructure: {0}", i.Name));
                    try
                    {
                        _infrastructures.Add(InfrastructureImpl.Build(i.Name, new Environment
                        {
                            DataDir = i.FullName,
                            BinDir = binDir.FullName,
                            WorkingDir = workingDir.FullName,
                            WorkingIdentity = workingIdentity
                        }));
                        _state.Add("OK");
                    }
                    catch(Exception ex)
                    {
                        _state.Add(String.Format("Error: {0}", ex.Message));
                    }
                }

                _initialized = true;
            }
        }

        #endregion
    }

    public abstract class HostApplication : HttpApplication
    {
        public void Application_Start(object sender, EventArgs e)
        {
            HostRuntime.Initialize();
        }
    }

#if CLOUD

    public class HostRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            HostRuntime.Initialize();
            return base.OnStart();
        }
    }

#endif
}